﻿#region COPYRIGHT
//--------------------------------------------------------------------------------
// <copyright file="Vector2Extensions.cs" company="starLiGHT Entertainment Studios">
//    Copyright (c) 2007, 2008, 2009, 2010 
//       Roland Rosenkranz (Glatzemann@email.de)
// </copyright>
// <license>
//   This file is part of starLiGHT.Core.
//
//   starLiGHT.Core is free software: you can redistribute it and/or modify
//   it under the terms of the GNU Lesser General Public License as published by
//   the Free Software Foundation, either version 3 of the License, or
//   (at your option) any later version.
//
//   starLiGHT.Core is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU Lesser General Public License for more details.
//
//   You should have received a copy of the GNU Lesser General Public License
//   along with starLiGHT.Core. If not, see http://www.gnu.org/licenses/.
//    
//   ADDITIONAL (commercial) LICENSES for starLiGHT.Core are available on request.
// </license>
// <version>
// **************[ starLiGHT.Engine SVN ]**********************
// * $Rev:: 620                   $:  Revision of last commit *
// * $Author:: unknown            $:  Author of last commit   *
// * $Date:: 2010-12-07 15:23:58 #$:  Date of last commit     *
// ************************************************************
// </version>
//--------------------------------------------------------------------------------
#endregion

namespace starLiGHT
{
    #region Using Statements
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Text;
    using Microsoft.Xna.Framework;

    #endregion

    public static class Vector2Extensions
    {
        public static bool IsValid(this Vector2 v)
        {
            if (float.IsNaN(v.X))
            {
                return false;
            }

            if (float.IsNaN(v.Y))
            {
                return false;
            }

            return float.NegativeInfinity < v.X && v.X < float.PositiveInfinity && float.NegativeInfinity < v.Y && v.Y < float.PositiveInfinity;
        }

        public static Vector2 FromString(this Vector2 v, string s)
        {
            s = s.Replace("{", string.Empty).Replace("}", string.Empty);
            s = s.ToUpperInvariant().Replace("X=", string.Empty).Replace("Y=", string.Empty);
            s = s.ToUpperInvariant().Replace("X:", string.Empty).Replace("Y:", string.Empty);
            s = s.ToLowerInvariant().Replace("f", string.Empty);
            string[] parts = s.Split(new char[] { ' ', ',', ':' });

            CultureInfo culture = new CultureInfo("en-US");

            float x = float.Parse(parts[0], culture);
            float y = float.Parse(parts[1], culture);
            v = new Vector2(x, y);

            return v;
        }

        public static Vector2 Abs(this Vector2 v)
        {
            Vector2 ret = new Vector2();
            ret.X = Math.Abs(v.X);
            ret.Y = Math.Abs(v.Y);
            return ret;
        }

        public static float Item(this Vector2 v, int index)
        {
            if (index == 0)
            {
                return v.X;
            }
            else if (index == 1)
            {
                return v.Y;
            }
            else
            {
                throw new ArgumentException("invalid index (0..1) for a vector2");
            }
        }

        public static void Item(this Vector2 v, int index, float value)
        {
            if (index == 0)
            {
                v.X = value;
            }
            else if (index == 1)
            {
                v.Y = value;
            }
            else
            {
                throw new ArgumentException("invalid index (0..1) for a vector2");
            }
        }

        /// <summary>
        /// Perform the cross product on two vectors. In 2D this produces a scalar.
        /// </summary>
        /// <param name="a">
        /// The first Vector2 to calculate the cross product
        /// </param>
        /// <param name="b">
        /// The second Vector2 to calculate the cross product
        /// </param>
        /// <returns>
        /// Returns the cross product of vector a and b
        /// </returns>
        public static float Cross(this Vector2 a, Vector2 b)
        {
            return (a.X * b.Y) - (a.Y * b.X);
        }

        /// <summary>
        /// Perform the cross product on a vector and a scalar. In 2D this produces
        /// a vector.
        /// </summary>
        /// <param name="a">
        /// The Vector2 to calculate the cross product
        /// </param>
        /// <param name="s">
        /// The scalar to calculate the cross product
        /// </param>
        /// <returns>
        /// Returns the cross product of vector a and scalar s
        /// </returns>
        public static Vector2 Cross(this Vector2 a, float s)
        {
            Vector2 ret = new Vector2();
            ret.X = s * a.Y;
            ret.Y = -s * a.X;
            return ret;
        }

        /// <summary>
        /// Perform the cross product on a vector and a scalar. In 2D this produces
        /// a vector.
        /// </summary>
        /// <param name="s">
        /// The scalar to calculate the cross product
        /// </param>
        /// <param name="a">
        /// The Vector2 to calculate the cross product
        /// </param>
        /// <returns>
        /// Returns the cross product of vector a and scalar s
        /// </returns>
        public static Vector2 Cross(this float s, Vector2 a)
        {
            Vector2 ret = new Vector2();
            ret.X = -s * a.Y;
            ret.Y = s * a.X;
            return ret;
        }

        public static Vector2 Perpendicular(this Vector2 vector)
        {
            return new Vector2(-vector.Y, vector.X);
        }

        public static Vector2 PerpendicularLeft(this Vector2 vector)
        {
            return new Vector2(vector.Y, -vector.X);
        }

        public static Vector2 Round(this Vector2 v)
        {
            return new Vector2((float)Math.Round((double)v.X), (float)Math.Round((double)v.Y));
        }

        public static Vector2 Round(this Vector2 v, int decimals)
        {
            double x = System.Math.Round(v.X, decimals);
            double y = System.Math.Round(v.Y, decimals);
            return new Vector2((float)x, (float)y);
        }

        public static Vector2 Rotate(this Vector2 v, float radians)
        {
            float c = (float)Math.Cos(radians);
            float s = (float)Math.Sin(radians);
            return new Vector2((c * v.X) - (s * v.Y), (s * v.X) + (c * v.Y));
        }

        public static void Rotate(this Vector2 v, float radians, out Vector2 ret)
        {
            ret = v.Rotate(radians);
        }
    }
}
